home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.3d26 source / tn3270 / scrap.c < prev    next >
Text File  |  1991-01-21  |  16KB  |  713 lines

  1. /*
  2.  *  tn3270 for the Macintosh Source Code
  3.  *  Brown University Computing and Information Services
  4.  *  Version 2.3d21, January 17, 1991
  5.  *  Copyright (c) 1988, 1989, 1990, 1991 by Brown University and by
  6.  *  Peter John DiCamillo.
  7.  *
  8.  *  Permission is granted to any individual or institution to use, copy,
  9.  *  or redistribute the binary version of this software and its
  10.  *  documentation provided this notice and the copyright notices are
  11.  *  retained.  Permission is granted to any individual or non-profit
  12.  *  institution to use, copy, modify, or redistribute the source files
  13.  *  of this software provided this notice and the copyright notices are
  14.  *  retained.  This software may not be distributed for profit, either
  15.  *  in original form or in derivative works, nor can the source be
  16.  *  distributed to other than an individual or a non-profit institution.
  17.  *  Any  individual or group interested in seeing and/or using these
  18.  *  source files but who are prevented from doing so by the above
  19.  *  constraints should contact Don Wolfe, Assistant Vice-President for
  20.  *  Computer Systems at Brown University, (401) 863-7250, for possible
  21.  *  software licensing of the source developed at Brown.
  22.  *
  23.  *  Brown University and Peter John DiCamillo make no representations
  24.  *  about the suitability of this software for any purpose.
  25.  *
  26.  *  BROWN UNIVERSITY AND PETER JOHN DICAMILLO GIVE NO WARRANTY, EITHER
  27.  *  EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
  28.  *  INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
  29.  *  WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
  30.  *
  31.  */
  32.  
  33. #define __SEG__ 3270seg2
  34.  
  35. #include <Scrap.h>
  36. #include "maclib.h"
  37. #include "termdef.h"
  38. #include "globals.h"
  39.  
  40. extern short maxcnt, maxoff, scrhsize, scrhoff;
  41. extern Handle alaxtabh;
  42. static char tableflag = 0;
  43. static char textflag = 0;
  44. static char calcflag;
  45. static long calcsize;
  46. static unsigned char * scrapptr;
  47. static unsigned char * expresult;
  48. static unsigned short * expresattr;
  49. unsigned char cutflag = 0;
  50.  
  51. OSErr newscrap()
  52. {
  53. long allocsize;
  54. scrapline * sp;
  55. unsigned char * chrptr;
  56. short i;
  57.  
  58. /* Return if there is already a scrap of the proper width */
  59. if ((scrapstart != 0) && (scrapwidth == ses_altcols)) {
  60.     return(noErr);
  61.     }
  62.  
  63. /* Remove an existing scrap */
  64. if (scrapstart != 0) {
  65.     removescrap();
  66.     }
  67.     
  68. /* Allocate new scrap */
  69.  
  70. scrapalloc = ses_altrows;        /* permanent allocation is one screen */
  71. scrapwidth = ses_altcols;        /* width always matches widest possible */
  72. allocsize = sizeof(struct scrapline) * scrapalloc;
  73. allocsize += scrapalloc * scrapwidth * 3;        /* 1 byte for char, 2 for attrs. */
  74. allocsize += scrapwidth * 3;        /* for expresult and expresattr */
  75. scrapstart = (scrapline *)myNewPtr(allocsize);
  76. if (scrapstart == 0L) {
  77.     return(1);
  78.     }
  79. chrptr = (unsigned char *)scrapstart;
  80. chrptr += sizeof(struct scrapline) * scrapalloc;
  81. sp = scrapstart;
  82. for (i=0; i < scrapalloc-1; i++) {
  83.     sp->nextline = sp + 1;
  84.     sp->text = chrptr;
  85.     chrptr += scrapwidth;
  86.     sp->attr = (unsigned short *)chrptr;
  87.     chrptr += scrapwidth * 2;
  88.     sp++;
  89.     }
  90. sp->nextline = 0;
  91. sp->text = chrptr;
  92. chrptr += scrapwidth;
  93. sp->attr = (unsigned short *)chrptr;
  94. chrptr += scrapwidth * 2;
  95.  
  96. expresult = chrptr;
  97. chrptr += scrapwidth;
  98. expresattr = (unsigned short *)chrptr;
  99.  
  100. scrapsize = 0;            /* no lines in use */
  101. return(0);
  102. }
  103.  
  104. removescrap()
  105. {
  106. scrapline *sp, *nextsp;
  107.  
  108. if (scrapstart == 0) {
  109.     return;
  110.     }
  111.  
  112. exportscrap(1);                /* copy private scrap to desk scrap */
  113.  
  114.                                 /* return private scrap storage */
  115. sp = scrapstart;
  116. sp += scrapalloc - 1;            /* sp -> last permanent element */
  117. nextsp = sp->nextline;            /* nextsp -> first extra element, if any */
  118. while (nextsp != 0) {            /* free each extra element */
  119.     sp = nextsp;
  120.     nextsp = sp->nextline;
  121.     DisposPtr(sp);
  122.     }
  123. DisposPtr(scrapstart);            /* free permanent elements */
  124. scrapstart = 0;
  125. }
  126.  
  127. importscrap()
  128. {
  129. scrapsize = 0;    /* temp */
  130. }
  131.  
  132. exportscrap(endflag)
  133. char endflag;
  134. {
  135. unsigned char * scrapmem;
  136. OSErr rc;
  137.  
  138. if (scrapsize == 0) return;    /* nothing to do if no scrap */
  139.  
  140.                             /* calculate size of exported scrap */
  141. calcsize = 0;
  142. calcflag = 1;
  143. doexport();
  144.                             /* return if size = 0 */
  145. if (calcsize == 0) return;
  146.                             /* allocate memory to hold scrap */
  147. scrapmem = (unsigned char *)myNewPtr(calcsize);
  148. if (scrapmem == 0) {
  149.     beep();
  150.     return;
  151.     }
  152.                             /* initialize scrap */
  153. rc = ZeroScrap();
  154. if (rc != 0) {
  155.     DisposPtr(scrapmem);
  156.     beep();
  157.     return;
  158.     }
  159.                             /* copy data to scrap  and return storage */
  160. scrapptr = scrapmem;
  161. calcflag = 0;
  162. doexport();
  163. rc = PutScrap(calcsize, 'TEXT', scrapmem);
  164. DisposPtr(scrapmem);
  165. if (rc != 0) {
  166.     beep();
  167.     return;
  168.     }
  169.                             /* if end call, load scrap into memory */
  170. if (endflag) LoadScrap();
  171. }
  172.  
  173. doexport()
  174. {
  175. register short col;
  176. short startoff, len, colstart, colend;
  177. short linecount;
  178. char expstate, initsel, sel, anytext;
  179. scrapline * sp;
  180. scrapline currline;
  181.  
  182. sp = scrapstart;
  183. linecount = 0;
  184. anytext = 0;
  185. while (linecount < scrapsize) {
  186.     currline = *sp;    /* make local copy of current line */
  187.                     /* find first selected printable character */
  188.     colstart = 0;
  189.     initsel = 0;
  190.     while (colstart < scrapwidth) {
  191.         if ((currline.attr)[colstart] & 0x0020) {
  192.             if (((currline.text)[colstart] != 0) &&
  193.                 ((currline.text)[colstart] != 0x40) &&
  194.                 (((currline.attr)[colstart] & 0x8000) == 0)) {
  195.                 if ((initsel == 0) && textflag && anytext) expbreak();
  196.                 anytext = initsel = 1;
  197.                 break;
  198.                 }
  199.             else {
  200.                 if ((initsel == 0) && textflag) {
  201.                     expendline();
  202.                     anytext = 0;
  203.                     }
  204.                 initsel = 1;
  205.                 }
  206.             }
  207.         colstart++;
  208.         }
  209.                     /* if no printable characters, output null line */
  210.     if (colstart == scrapwidth) {
  211.         if (initsel) {
  212.             expendline();
  213.             anytext = 0;
  214.             }
  215.         linecount++;
  216.         sp = sp->nextline;
  217.         continue;
  218.         }
  219.                     /* find last printable character */
  220.     colend = scrapwidth - 1;
  221.     while (colend >= 0) {
  222.         if (((currline.attr)[colend] & 0x0020) &&
  223.             ((currline.text)[colend] != 0) &&
  224.             ((currline.text)[colend] != 0x40) &&
  225.             (((currline.attr)[colend] & 0x8000) == 0)) break;
  226.         else colend--;
  227.         }
  228.     expstate = 0;
  229.     initsel = 0;
  230.     for (col = colstart; col <= colend; col++) {
  231.         sel = ((currline.attr)[col] & 0x0020) != 0;
  232.         if (tableflag || (!initsel)) { 
  233.             sel = sel && ((currline.text)[col] != 0)
  234.                       && ((currline.text)[col] != 0x40)
  235.                       && (((currline.attr)[col] & 0x8000) == 0);
  236.             initsel = sel;
  237.             }
  238.         switch(expstate) {
  239.             case 0:                        /* before first field */
  240.                         if (sel) {
  241.                             startoff = col;
  242.                             len = 1;
  243.                             expstate = 1;
  244.                             }
  245.                         break;
  246.             case 1:                        /* within field */
  247.                         if (sel) {
  248.                             len++;
  249.                             }
  250.                         else {
  251.                             expfield(&currline, startoff, len);
  252.                             startoff = col;
  253.                             len = 1;
  254.                             expstate = 2;
  255.                             initsel = 0;
  256.                             }
  257.                         break;
  258.             case 2:                        /* between fields */
  259.                         if (sel) {
  260.                             expbreak(&currline, startoff, len);
  261.                             startoff = col;
  262.                             len = 1;
  263.                             expstate = 1;
  264.                             }
  265.                         else {
  266.                             len++;
  267.                             }
  268.                         break;
  269.             default:    
  270.                         break;
  271.             }
  272.         }
  273.     switch(expstate) {        /* end-of-line processing */
  274.         case 0:                        /* before first field */
  275.                     break;
  276.         case 1:                        /* within field */
  277.                     expfield(&currline, startoff, len);
  278.                     if (!textflag) expendline();
  279.                     break;
  280.         case 2:                        /* between fields */
  281.                     if (!textflag) expendline();
  282.                     break;    
  283.         default:    
  284.                     break;
  285.         }
  286.  
  287.     linecount++;
  288.     sp = sp->nextline;
  289.     }
  290. }
  291.  
  292. expfield(sp, offset, len)
  293. scrapline * sp;
  294. register short offset, len;
  295. {
  296. short linelen;
  297. register short i;
  298. char alaflag, dcflag;
  299. unsigned char alatrans();
  300. scrapline currline;
  301.  
  302. currline = *sp;        /* make copy of current line */
  303. /* adjust offset and length to eliminate leading blanks, nulls, and
  304.    attributes (shouldn't happen).                                    */
  305. while (len > 0) {
  306.     if (((currline.text)[offset] == 0x00) ||
  307.         ((currline.text)[offset] == 0x40) ||
  308.         ((currline.attr)[offset] & 0x8000)) {
  309.         offset++;
  310.         len--;
  311.         }
  312.     else break;
  313.     }
  314.  
  315. /* adjust length to eliminate trailing blanks, nulls, and attributes */
  316. while (len > 0) {
  317.     if (((currline.text)[offset+len-1] == 0x00) ||
  318.         ((currline.text)[offset+len-1] == 0x40) ||
  319.         ((currline.attr)[offset+len-1] & 0x8000)) {
  320.         len--;
  321.         }
  322.     else break;
  323.     }
  324.  
  325. /* skip field if no printable characters (shouldn't happen) */
  326. if (len == 0) return;
  327.  
  328. /* copy field to buffer, handling nulls, and replacing attribute
  329.    bytes by blanks                                              */
  330. linelen = 0;
  331. dcflag = 0;
  332. alaflag = (stdfont == ALAFONT);
  333. for (i=0; i < len; i++) {
  334.     if ((currline.attr)[offset+i] & 0x8000) { 
  335.         expresult[linelen] = 0x40;
  336.         expresattr[linelen++] = (currline.attr)[offset+i];
  337.         if (alaflag) {
  338.             expresattr[linelen] &= 0xff00;
  339.             dcflag = 0;
  340.             }
  341.         }
  342.     else if ((currline.text)[offset+i] == 0x00) {
  343.         if (cs.repnull) {
  344.             expresult[linelen] = 0x40;
  345.             expresattr[linelen++] - (currline.attr)[offset+i];
  346.             if (alaflag) {
  347.                 expresattr[linelen] &= 0xff00;
  348.                 dcflag = 0;
  349.                 }
  350.             }
  351.         }
  352.     else {
  353.         if (alaflag) {
  354.             if (alatype((currline.text)+offset+i) == 2) {    /* is a diacritic */
  355.                 expresult[linelen] = (currline.text)[offset+i];
  356.                 expresattr[linelen++] = (currline.attr)[offset+i] & 0xff00;
  357.                 dcflag = 1;
  358.                 }
  359.             else {                                        /* not a diacritic */
  360.                 if (dcflag) {
  361.                     if ((currline.text)[offset+i] != 0x40) {
  362.                         expresattr[linelen-1] |= (currline.text)[offset+i];
  363.                         }
  364.                     dcflag = 0;
  365.                     }
  366.                 else {
  367.                     expresult[linelen] = (currline.text)[offset+i];
  368.                     expresattr[linelen++] = (currline.attr)[offset+i] & 0xff00;
  369.                     }
  370.                 }
  371.             }
  372.         else {
  373.             expresult[linelen] = (currline.text)[offset+i];
  374.             expresattr[linelen++] = (currline.attr)[offset+i];
  375.             }
  376.         }
  377.     }
  378.  
  379. /* translate from EBCDIC to Mac ASCII */
  380. for (i=0; i < linelen; i++)
  381.     if (expresattr[i] & 0x4000) {        /* APL character */
  382.         expresult[i] = (*xtabh)[expresult[i] + 256];
  383.         }
  384.     else {
  385.         if (nl_handle != 0) {
  386.             expresult[i] = (*xtabh)[nltab[expresult[i]]];
  387.             }
  388.         else {
  389.             if (alaflag) {
  390.                 expresult[i] = alatrans(expresult[i], expresattr[i] & 0xff);
  391.                 }
  392.             else {
  393.                 expresult[i] = (*xtabh)[expresult[i]];
  394.                 }
  395.             }
  396.         }
  397.  
  398. /* add to the desk scrap */
  399. myPutScrap(linelen, expresult);
  400. }
  401.  
  402. unsigned char alatrans(dc, chr)
  403. unsigned char dc, chr;
  404. {
  405. unsigned char *chrlist, *dclist, *dcdata;
  406. register short i;
  407. short chrindex, dcindex;
  408. unsigned char c;
  409.  
  410. if (chr == 0) return((*xtabh)[dc+512]);        /* no diacritic */
  411.  
  412. chrlist = (*alaxtabh);
  413. dclist = chrlist+16;
  414. dcdata = chrlist+32;
  415.                             /* get table index for character */
  416. chrindex = -1;
  417. for (i=0; i < 16; i++) {
  418.     if (chrlist[i] == 0) break;
  419.     if (chr == chrlist[i]) {
  420.         chrindex = i;
  421.         break;
  422.         }
  423.     }
  424.     
  425. if (chrindex < 0) return((*xtabh)[chr+512]);
  426.                             /* get table index for diacritic */
  427. dcindex = -1;
  428. for (i=0; i < 16; i++) {
  429.     if (dclist[i] == 0) break;
  430.     if (dc == dclist[i]) {
  431.         dcindex = i;
  432.         break;
  433.         }
  434.     }
  435.     
  436. if (dcindex < 0) return((*xtabh)[chr+512]);
  437.  
  438. c = dcdata[(dcindex << 4) + chrindex];
  439. if (c == 0) return((*xtabh)[chr+512]);
  440. else return(c);
  441. }
  442.  
  443. expbreak(offset, len)
  444. short offset, len;
  445. {
  446. unsigned char breakchar[1];
  447.  
  448. if (tableflag) breakchar[0] = 0x09;
  449. else breakchar[0] = 0x20;
  450. myPutScrap(1, breakchar); 
  451. }
  452.  
  453. expendline()
  454. {
  455. static unsigned char endchar[1] = 0x0d;
  456.  
  457. myPutScrap(1, endchar);
  458. }
  459.  
  460. myPutScrap(len, data)
  461. short len; unsigned char * data;
  462. {
  463. if (calcflag) {
  464.     calcsize += len;
  465.     return;
  466.     }
  467. memcpy(scrapptr, data, len);
  468. scrapptr += len;
  469. }
  470.  
  471. scrapcut(append)
  472. char append;
  473. {
  474. register unsigned short i, offset, a, attroff;
  475. char protfield, protflag;
  476.  
  477. tableflag = textflag = 0;
  478. scopy(append);
  479.  
  480. if (!fmtscrn) {
  481.     cutflag = 1;
  482.     for (i=0; i < maxcnt; i++) {
  483.         if (atrbuff[i] & 0x0020) dselchar(i, 0);
  484.         }
  485.     cutflag = 0;
  486.     invldscr();
  487.     return;
  488.     }
  489.  
  490. offset=firstattr();
  491. cutflag = 1;
  492. protflag = 0;
  493. for (i=0; i < maxcnt; i++) {
  494.     a = atrbuff[offset];
  495.     if (a & 0x8000) {        /* handle attribute byte */
  496.         protfield = (a & 0x2000) != 0;
  497.         attroff = offset;
  498.         }
  499.     if (((a & 0x8020) == 0x0020) && (!protfield)) {
  500.         dselchar(offset, attroff);
  501.         }
  502.     else {
  503.         if (a & 0x0020) protflag = 1;
  504.         }
  505.     offset++;
  506.     if (offset > maxoff) offset = 0;
  507.     }
  508. invldscr();
  509. if (protflag) beep();
  510. cutflag = 0;
  511. }
  512.  
  513. scrapcopy(append)
  514. char append;
  515. {
  516. tableflag = textflag = 0;
  517. scopy(append);
  518. }
  519.  
  520. scrappaste()
  521. {
  522. char message[80];
  523. char dbsave;
  524.  
  525. sprintf(message, "Sorry, Paste isn't implemented yet");
  526. arrowcursor();
  527. dbsave = cs.dblevel;
  528. cs.dblevel = 1;
  529. dbdlg(message);
  530. cs.dblevel = dbsave;
  531. }
  532.  
  533. scrapclear()
  534. {
  535. selclear(0x00);
  536. }
  537.  
  538. scrapcopytable(append)
  539. char append;
  540. {
  541. tableflag = 1;
  542. textflag = 0;
  543. scopy(append);
  544. }
  545.  
  546. scrapcopytext(append)
  547. char append;
  548. {
  549. tableflag = 0;
  550. textflag = 1;
  551. scopy(append);
  552. }
  553.  
  554. scopy(append)
  555. char append;
  556. {
  557. register short rowoff, coloff;
  558. short i;
  559. char found, scrapinit, scrapappend;
  560. scrapline * sp, *nextsp;
  561. unsigned char *chrptr;
  562. long allocsize;
  563.  
  564. scrapinit = scrapappend = 0;
  565. for (rowoff = 0; rowoff < maxcnt; rowoff += scrhsize) {
  566.     found = 0;
  567.     for (coloff = 0; coloff < scrhsize; coloff++)
  568.         if (atrbuff[rowoff+coloff] & 0x0020) {
  569.             found = 1;
  570.             break;
  571.             }
  572.     if (!found) continue;
  573.     if (!scrapinit) {        /* set sp before adding first line */
  574.         scrapinit = 1;
  575.         if (!append) scrapsize = 0;
  576.         sp = scrapstart;
  577.         if (scrapsize > 1)
  578.             for (i=0; i < scrapsize-1; i++) sp = sp->nextline;
  579.         }
  580.                             /* add new line after last line */
  581.     if (scrapsize > 0) {
  582.         if (sp->nextline == 0) {
  583.             allocsize = sizeof(struct scrapline);
  584.             allocsize += scrapwidth * 3;
  585.             sp->nextline = (struct scrapline *)myNewPtr(allocsize);
  586.             if (sp->nextline == 0) {
  587.                 beep();
  588.                 return;
  589.                 }
  590.             scrapappend = 1;
  591.             (sp->nextline)->nextline = 0;
  592.             chrptr = (unsigned char *)sp->nextline;
  593.             chrptr += sizeof(struct scrapline);
  594.             (sp->nextline)->text = chrptr;
  595.             chrptr += scrapwidth;
  596.             (sp->nextline)->attr = (unsigned short *)chrptr;
  597.              }
  598.         sp = sp->nextline;
  599.         }
  600.     setmem(sp->text, scrapwidth, 0);
  601.     movmem(chrbuff+rowoff, sp->text, scrhsize);
  602.     setmem(sp->attr, scrapwidth*2, 0);
  603.     movmem(atrbuff+rowoff, sp->attr, scrhsize*2);
  604.     scrapsize++;
  605.     }
  606.         /* return if we didn't do anything or appended new lines */
  607. if ((!scrapinit) || scrapappend) return;
  608.         /* free lines previously appended we no longer need */
  609. if (scrapsize < scrapalloc) {
  610.     sp = scrapstart;
  611.     sp += scrapalloc - 1;            /* sp -> last permanent element */
  612.     }
  613.     
  614. nextsp = sp->nextline;            /* nextsp -> first unneeded element, if any */
  615. sp->nextline = 0;                /* end chain at last element needed */
  616. while (nextsp != 0) {
  617.     sp = nextsp;
  618.     nextsp = sp->nextline;
  619.     DisposPtr(sp);
  620.     }
  621. }
  622.  
  623. dselchar(start, attroff)        /* delete selected characters */
  624. unsigned short start, attroff;
  625. {
  626. register unsigned short src, padcount;
  627. unsigned short i, end, dest;
  628.  
  629. if (fmtscrn) {    
  630.     i = atrbuff[attroff];
  631.     }
  632. else i = 0;
  633.                         /* calculate last position to possibly change */
  634. if (cs.repnull && fmtscrn) {
  635.     if (start > 0) end = start - 1;
  636.     else end = maxoff;
  637.     }
  638. else {
  639.     end = ((start / scrhsize) + 1) * scrhsize - 1;    /* last loc. on line */
  640.     }
  641.  
  642. src = dest = start;
  643. padcount = 0;
  644. while (1) {
  645.     if (atrbuff[src] & 0x8000) {
  646.         break;
  647.         }
  648.     if (atrbuff[src] & 0x0020) {
  649.         padcount++;
  650.         }
  651.     else {
  652.         newchar(dest, chrbuff[src], atrbuff[src], i);
  653.         dest++;
  654.         if (dest == maxcnt) dest = 0;
  655.         }
  656.     if (src == end) break;        /* exit if just did the last one */
  657.     src++;
  658.     if (src == maxcnt) src = 0;
  659.     } 
  660. while (padcount > 0) {
  661.     newchar(dest, 0x00, 0, i);
  662.     dest++;
  663.     if (dest == maxcnt) dest = 0;
  664.     padcount--;
  665.     }
  666. newwrite(0);
  667. if (fmtscrn) atrbuff[attroff] |= 0x0100;    /* set MDT bit */
  668. }
  669.  
  670. selclear(fillchar)
  671. unsigned char fillchar;
  672. {
  673. unsigned char t;
  674. register unsigned char prot;
  675. register short a, attroff, chroff, i;
  676. char changeflag;
  677.  
  678. if (kblock) {
  679.     beep();
  680.     return;
  681.     }
  682. changeflag = 0;
  683. if (fmtscrn) a = firstattr();
  684. else a = 0;
  685. for (i=0; i < maxcnt; i++) {
  686.     if (atrbuff[a] & 0x8000) {                /* attribute */
  687.         prot = (atrbuff[a] & 0x2000) != 0;
  688.         attroff = a;        /* save attribute offset */
  689.         }
  690.     else if (fmtscrn) {                /* character, formatted screen */
  691.         if ((atrbuff[a] & 0x0020) && (!prot)) {
  692.             newchar(a, fillchar, 0, atrbuff[attroff]);
  693.             atrbuff[attroff] |= 0x0100;        /* set MDT bit */
  694.             changeflag = 1;
  695.             }
  696.         }
  697.     else {                            /* character, unformatted screen */
  698.         if (atrbuff[a] & 0x0020) {
  699.             newchar(a, fillchar, 0, 0);
  700.             changeflag = 1;
  701.             }
  702.         }
  703.     a++;
  704.     if (a == maxcnt) a = 0;
  705.     }
  706. if (changeflag) {
  707.     newwrite(0);
  708.     }
  709. else {
  710.     beep();
  711.     kerr(1);
  712.     }
  713. }